...loading
2024-10-21
자바스크립트는 싱글 스레드 언어다. 즉, 자바스크립트 엔진은 한 번에 하나의 태스크만 실행할 수 있다. 예를 들어, 자바스크립트에서 함수 A,B,C를 모두 실행하고자 한다면 엔진은 각 함수를 순차적으로 실행하게 된다. 이처럼 코드를 순차적으로 처리하는 것을 동기(Synchronous) 처리라 한다.
동기 처리에는 한 가지 문제가 있다. 순차적으로 태스크를 처리하기 때문에 무거운 태스크를 만나게 되면 다음 작업이 밀리게 된다. 다음 작업을 처리하기 위해 무작정 기다려야하는 문제가 생기는 것이다. 그렇다면 만약 태스크를 병렬적으로 처리할 수 있다면 효율적이지 않을까.
앞선 동기 처리와 다르게, 여러 태스크들을 병렬적으로 처리하는 것을 비동기(Asynchronous) 처리라 한다. 이를 통해 앞선 동기 처리의 문제를 해결할 수 있다. 자바스크립트는 싱글 스레드 언어지만 이러한 상황을 위해 비동기로 처리되는 기능들을 몇몇 지원한다. 대표적으로 통신함수인 fetch와 스케줄링함수인 setTimeout이 이에 해당한다.
자바스크립트는 싱글 스레드 언어임에도 특정 비동기 처리가 가능한 이유는 동작 원리를 살펴보면 알 수 있다. 자바스크립트 코드는 자바스크립트 엔진이 내장된 브라우저에서 실행된다. 그리고 자바스크립트 엔진은 싱글 스레드로 동작하지만, 브라우저는 멀티 스레드로 동작한다. 여기에서 비동기 함수는 자바스크립트 엔진이 아닌 브라우저에 위임되어 처리되는 것이다.
<자바스크립트 동작 원리>
위의 그림에서 보는 바와 같이 자바스크립트 엔진은 Memory Heap과 Call Stack으로 구성된다. Memory Heap은 객체가 저장되는 메모리 공간이고 Call Stack은 실행 컨텍스트가 쌓인다. 자바스크립트 엔진은 단 하나의 Call Stack을 가지고 있기에, 현재 실행 중인 컨텍스트가 종료되기 전까지는 어떠한 작업도 실행되지 않는다. 따라서 자바스크립트 엔진은 동기 처리를 하게 되는 것이다.
비동기 처리는 브라우저에서 지원하는 Web Apis에서 처리된다. 예를 들어 setTimeOut이나 fetch와 같은 함수의 비동기 작업은 브라우저의 Web Apis에서 처리된다. 그리고 해당 비동기 작업이 처리되고 난 후 실행될 콜백함수는 Taks Queue에 쌓여 대기된다. Event Loop는 Call Stack에서 처리할 작업이 더이상 남아있지 않는 것이 확인된다면 Task Queue에서 대기 중인 작업을 Call Stack에 푸시하게 된다.
function timer() { console.log("time is out") } setTimeout(timer, 5000);
예를들어, 위와 같은 setTimeout함수를 실행했을 때 어떻게 동작하는지 알아보자.
비동기 처리는 여러 작업들을 효율적으로 처리하는데 장점이 있다. 하지만, 오히려 이 장점이 단점이 되는 경우도 존재한다. 만약 여러 비동기 작업들을 순차적으로 반환받고 싶은 경우가 그러하다.
예를 들어, 여러 네트워크 요청의 순차성을 보장받고 싶은 경우가 있다. 하지만 비동기 처리되는 통신함수들은 호출의 순서와 상관없이 랜덤으로 반환될 수 있다. 만약 제목을 입력하면 서버에서 해당 제목의 포스팅을 가져오는 함수가 있다고 하자.
const getPosting = (title) => { fetch(`www.myServer.com/postings`, { body : JSON.stringfy({ title: title }) }).then(res=> res.json()) .then(res => { console.log(res) }) } getPosting('도쿄 여행일지 1편'); getPosting('도쿄 여행일지 2편');
getPosting 함수는 비동기 처리되기 때문에 1,2편이 순서대로 출력되는 것을 보장할 수 없다. 통신의 상태에 따라 2편이 먼저 출력될 수도 있는 것이다. 이럴 경우에 필요한 기능들이 Callback , Promise, async & await 이다. 해당 기능들을 통해 하나의 작업이 완료되면 다음 작업을 실행할 수 있게 된다. 해당 패턴들을 통해 비동기 처리들의 순차성을 보장할 수 있다. 자세한 사용법은 다른 포스팅에서 알아보고자 한다.
자바스크립트는 싱글 스레드 언어이지만, 자바스크립트 엔진의 런타임 환경인 브라우저와 협력하여 특정 비동기 처리들을 수행하게 된다. 이는 브라우저가 멀티 스레드로 동작하기 때문에 가능한 것이다. 만약 모든 비동기 처리를 요하는 함수들을 자바스크립트 엔진에서 처리하게 된다면, 다수의 블로킹 현상이 발생할 수 있다. 추가적으로 동기적으로 실행될 모든 함수들을 마법처럼 비동기 처리로 바꿀 수는 없다. 브라우저에서 지원하는 통신함수와 타이머 함수와 같은 특정 API들에 한해 비동기 처리가 가능하다.
Comments